package com.wuster.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.wuster.constant.MessageConstant;
import com.wuster.constant.ProductConstant;
import com.wuster.entity.Category;
import com.wuster.entity.Product;
import com.wuster.entity.ProductVO;
import com.wuster.entity.dto.ProductDTO;
import com.wuster.exception.ProductException;
import com.wuster.mapper.CategoryMapper;
import com.wuster.result.PageResult;
import com.wuster.result.Result;
import com.wuster.result.ResultCodeEnum;
import com.wuster.service.ProductService;
import com.wuster.mapper.ProductMapper;
import com.wuster.utils.ThreadLocalUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

/**
* @author Wu
* @description 针对表【product】的数据库操作Service实现
* @createDate 2024-07-04 21:14:46
*/

@Service
@Slf4j
public class ProductServiceImpl extends ServiceImpl<ProductMapper, Product> implements ProductService{

    @Autowired
    ProductMapper productMapper;

    @Autowired
    CategoryMapper categoryMapper;


    //更新商品上下架状态
    @Override
    public Result setStatus(ProductDTO productDTO) {
        // status不能为空、只能为0或1
        Integer status = productDTO.getStatus();
        if (status == null || (status != ProductConstant.PRODUCT_SALE_STATUS && status != ProductConstant.PRODUCT_UN_SALE_STATUS)) {
            return Result.error(ResultCodeEnum.STATUS_IS_INVALID.getCode(), ResultCodeEnum.STATUS_IS_INVALID.getMessage());
        }
        // 商品是否存在？或被逻辑删除？
        if (getProductDeleteStatus(productDTO.getProductId())){
            return Result.error(ResultCodeEnum.PRODUCT_NOT_EXIST.getCode(), ResultCodeEnum.PRODUCT_NOT_EXIST.getMessage());
        }
        UpdateWrapper<Product> wapper = new UpdateWrapper<Product>()
                .eq("id", productDTO.getProductId())
                .set("state", productDTO.getStatus())
                .set("image", productDTO.getImg());

        int updateSum = productMapper.update(null, wapper);
        if (updateSum==0)
            return Result.error(ResultCodeEnum.FAILED_TO_UPDATE_STATUS.getCode(), ResultCodeEnum.FAILED_TO_UPDATE_STATUS.getMessage());
        return Result.success();
    }


    // 删除商品（逻辑删除）。注意点：逻辑删除的商品排序值设置为null，防止修改商品排序的时候出错
    @Override
    public Result delProduct(Long pid) {
        // 商品是否存在？或被逻辑删除？
        if (getProductDeleteStatus(pid)){
            return Result.error(ResultCodeEnum.PRODUCT_NOT_EXIST.getCode(), ResultCodeEnum.PRODUCT_NOT_EXIST.getMessage());
        }

        // 获取当前商品的排序号 nowProductOrdinal
        Product product = (Product) getDetailById(pid).getData();
        Integer nowProductOrdinal = product.getOrdinalNumber();

        // 更新待删除商品
        LambdaUpdateWrapper<Product> lambdaUpdateWrapper = new LambdaUpdateWrapper<Product>()
                .eq(Product::getId, pid)
                .set(Product::getIsdeleted, ProductConstant.PRODUCT_DELETE)
                .set(Product::getUpdateTime, LocalDateTime.now())
                .set(Product::getUpdateAdmin, getAdminId())
                .set(Product::getOrdinalNumber, null);
        int updateSum = productMapper.update(null, lambdaUpdateWrapper);
        if (updateSum == 0)
            return Result.error(ResultCodeEnum.DELETE_PRODUCT_FAIL.getCode(), ResultCodeEnum.DELETE_PRODUCT_FAIL.getMessage());

        // 删除商品后，该商品后面的所有商品排序 -1  (nowProductOrdinalNumber, maxOrdinalNumber]
        int maxOrdinal = getMaxOrdinalNumber();
        if (maxOrdinal != 0 && !nowProductOrdinal.equals(null) && maxOrdinal > nowProductOrdinal) //表中有数据 且 已删除的商品后面还有商品才更新
            updateOrdinalNumber(nowProductOrdinal, maxOrdinal);
        return Result.success();
    }


    // 添加商品
    @Override
    public Result addProduct(ProductDTO productDTO) {
        // 判断ProductDTO中必须字段不为空
        String msg = verifyFields(productDTO);
        if (msg != "right")
            return Result.error(ResultCodeEnum.PARAMETER_VALUE_EMPTY.getCode(), msg);
        // 字段限制
        if(productDTO.getPrice().compareTo(BigDecimal.ZERO) < 0 || productDTO.getStorage() < 0 ||productDTO.getWeight().compareTo(BigDecimal.ZERO) < 0){
            throw new ProductException(ResultCodeEnum.PARAMETER_VALUE_INVALID.getCode(),
                    ResultCodeEnum.PARAMETER_VALUE_INVALID.getMessage());
        }
        // 重复添加判断（name不能相同）
        String name = productDTO.getName();
        int sameAmount = selectByName(name);
        if (sameAmount != 0)
            return Result.error(ResultCodeEnum.PRODUCT_EXIST.getCode(), name+"已存在！不能重复添加。");

        // 对象属性拷贝，将productDTO属性拷贝给product
        Product product = new Product();
        BeanUtils.copyProperties(productDTO, product);

        // 设置product 一些属性的初始值. 销量为0，上架状态，创建时间，未删除
        product.setSales(0);
        product.setIsdeleted(ProductConstant.PRODUCT_UN_DELETE);
        product.setState(ProductConstant.PRODUCT_SALE_STATUS);
        product.setImage(productDTO.getImg());
        product.setCreateAdmin(Long.valueOf(getAdminId()));
        product.setCreateTime(LocalDateTime.now());

        // 添加商品后，商品排序设为最大
        product.setOrdinalNumber(1);
        // 后面所有商品的排序+1
        UpdateWrapper<Product> wrapper = new UpdateWrapper<>();
        wrapper.setSql("ordinal_number = ordinal_number + 1");
        productMapper.update(null,wrapper);

        productMapper.insert(product);
        return Result.success();
    }


    // 修改商品
    @Override
    public Result updateProduct(ProductDTO productDTO) {
        // 判断ProductDTO中必须字段不为空
        String msg = verifyFields(productDTO);
        if (msg != "right" || productDTO.getOrdinalNumber() == null)
            return Result.error(ResultCodeEnum.PARAMETER_VALUE_EMPTY.getCode(), msg);
        // 商品是否存在？或被逻辑删除？
        if (getProductDeleteStatus(productDTO.getProductId())){
            return Result.error(ResultCodeEnum.PRODUCT_NOT_EXIST.getCode(),
                    ResultCodeEnum.PRODUCT_NOT_EXIST.getMessage());
        }
        // 字段限制
        if(productDTO.getPrice().compareTo(BigDecimal.ZERO) < 0 || productDTO.getStorage() < 0 ||productDTO.getWeight().compareTo(BigDecimal.ZERO) < 0){
            throw new ProductException(ResultCodeEnum.PARAMETER_VALUE_INVALID.getCode(),
                    ResultCodeEnum.PARAMETER_VALUE_INVALID.getMessage());
        }

        // 对象属性拷贝，将productDTO属性拷贝给product
        Product product = new Product();
        BeanUtils.copyProperties(productDTO, product);

        // 设置product 一些属性的变化. 修改时间，修改用户
        product.setUpdateAdmin(Long.valueOf(getAdminId()));
        product.setUpdateTime(LocalDateTime.now());
        product.setState(productDTO.getStatus());
        product.setImage(productDTO.getImg());
        product.setImages(productDTO.getImages());

        // 更新商品前需要判断 商品的排序是否修改
        Integer newOrdinalNumber = productDTO.getOrdinalNumber();
        // 0.判断修改序号是否合法
        if (newOrdinalNumber <= 0 || newOrdinalNumber == null)
            return Result.error(500, "商品排序号非法");
        // 1.获取修改前序号
        Integer ordinalNumber = productMapper.selectById(productDTO.getProductId()).getOrdinalNumber();
        // 2.商品排序改变则更新区间内商品排序
        if (!ordinalNumber.equals(newOrdinalNumber)){
            updateOrdinalNumber(ordinalNumber, newOrdinalNumber);
        }

        // 更新商品
        LambdaUpdateWrapper<Product> lambdaUpdateWrapper = new LambdaUpdateWrapper<Product>()
                .eq(Product::getId, productDTO.getProductId());

        int updateSum = productMapper.update(product, lambdaUpdateWrapper);
        if (updateSum == 0)
            return Result.error(563, "修改失败！");

        return Result.success();
    }


    // 条件查询商品列表
    @Override
    public PageResult getList(Integer pageId, String name, Long categoryId) {
        // 定义查询构造器
        QueryWrapper<Product> wrapper = new QueryWrapper<>();
        if (name != null && !name.isEmpty()) {
            wrapper.like("name", name);
        }
        if (categoryId != null){
            wrapper.eq("category_id", categoryId);
        }
        wrapper.eq("isdeleted", ProductConstant.PRODUCT_UN_DELETE)
                .select("id", "image", "category_id", "name", "price", "state", "ordinal_number", "sales")
                .orderByAsc("ordinal_number");

        // 分页查询, TODO pageSize前端是否需要？
        int pageSize = 10;
        Page<Product> page = new Page<>(pageId, pageSize);
        Page<Product> productPage = productMapper.selectPage(page, wrapper);
        List<Product> productList = productPage.getRecords();

        // 对查询到的商品列表做一个过滤处理 去掉不需要的数据、修改属性名
        List<ProductVO> productVOList = new ArrayList<>();
        for (Product p : productList) {
            ProductVO pVO = new ProductVO();
            BeanUtils.copyProperties(p, pVO);
            pVO.setImg(p.getImage());
            pVO.setStatus(p.getState());
            productVOList.add(pVO);
        }

        PageResult pageResult = new PageResult(productPage.getTotal(), pageId, productVOList);
        return pageResult;
    }


    // 根据id查询商品详情
    @Override
    public Result getDetailById(Long pid) {
        // 商品是否存在？或被逻辑删除？
        if (getProductDeleteStatus(pid)) {
            return Result.error(ResultCodeEnum.PRODUCT_NOT_EXIST.getCode(), ResultCodeEnum.PRODUCT_NOT_EXIST.getMessage());
        }
        Product product = productMapper.selectById(pid);
        // 查询商品所属的分类名
        Category category = categoryMapper.selectById(product.getCategoryId());
        // 该分类不存在，未分类
        if (category == null)
            product.setCategoryName("未分类");
        else
            product.setCategoryName(category.getName());
        return Result.success(product);
    }


    // =====================================================================================================

    // 验证添加商品中的各个字段
    private String verifyFields(ProductDTO p) {
        if (p.getName() == null || p.getName().trim().isEmpty())
            return "商品名为空！";
        else if (!(p.getName() instanceof String))
            return "商品名必须是字符或字符串！";
        else if (p.getCategoryId() == null)
            return "分类id为空！";
        else if (p.getPrice() == null)
            return "价格为空！";
        else if (p.getIntroduction() == null || p.getIntroduction().trim().isEmpty())
            return "商品简介为空！";
        else if (p.getImg() == null || p.getImg().isEmpty())
            return "预览图为空";
        else if (p.getImages() == null || p.getImages().isEmpty())
            return "商品相册为空";
        else if (p.getWeight() == null)
            return "重量为空";
        else if (p.getStorage() == null)
            return "库存字段非法";
        else if (p.getWarn() == null || p.getWarn().trim().isEmpty())
            return "商品警告字段为空！";

        return "right";
    }

    // 查找是否已有名称为name 且没有逻辑删除 的商品
    private int selectByName(String name) {
        LambdaQueryWrapper<Product> queryWrapper = new LambdaQueryWrapper<Product>()
                .eq(Product::getName, name)
                .eq(Product::getIsdeleted, ProductConstant.PRODUCT_UN_DELETE);
        Product product = productMapper.selectOne(queryWrapper);
        if (product != null)
            return 1;
        return 0;
    }

    // 修改商品排序
    private void updateOrdinalNumber(Integer oldOrdinal, Integer newOrdinal) {

        UpdateWrapper<Product> wrapper = new UpdateWrapper<>();
        if (oldOrdinal > newOrdinal) {
            // 从后到前， [new, old) 之间的商品排序+1
            wrapper.setSql("ordinal_number = ordinal_number + 1")
                    .between("ordinal_number", newOrdinal, oldOrdinal-1);

        } else {
            // 从前到后,（new, old] -1
            wrapper.setSql("ordinal_number = ordinal_number - 1")
                    .between("ordinal_number", oldOrdinal+1, newOrdinal);
        }
        productMapper.update(null, wrapper);
    }


    // 根据商品id查询商品是否不存在或 处于删除状态, 1表示删除
    public boolean getProductDeleteStatus(Long pid){
        Product product = productMapper.selectById(pid);
        if (product == null || product.getIsdeleted() == ProductConstant.PRODUCT_DELETE) {
            return true;
        }
        return false;
    }

    // 获取商品的最大排序号
    // 注意点，sql中涉及到聚合函数的查询时，要使用selectObjs而不是selectOne
    public Integer getMaxOrdinalNumber(){
        QueryWrapper<Product> queryWrapper = new QueryWrapper<Product>()
                .select("MAX(ordinal_number)");
        List<Object> result = productMapper.selectObjs(queryWrapper);
        // product表中没有数据（逻辑删除）
        Integer maxOrdinal =  (Integer) result.get(0);
        if (result == null || result.isEmpty() || result.get(0) == null) return 0;
        return maxOrdinal;
    }

    //从ThreadLocal中获取当前管理员id
    public int getAdminId(){
        Map<String, Object> map = ThreadLocalUtil.get();
        int id = (int) map.get("id");

//        Long id = Long.valueOf(1);
        return id;
    }

}




